home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / libpr1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  29.1 KB  |  1,098 lines  |  [TEXT/R*ch]

  1. /*
  2.  * libpr1.c - a library of primitive object output routines, part 1 of 3.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  *
  6.  */
  7.  
  8. /*-----------------------------------------------------------------*/
  9. /* include section */
  10. /*-----------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16.  
  17. #include "lib.h"
  18. #include "drv.h"
  19.  
  20.  
  21. /*-----------------------------------------------------------------*/
  22. /* defines/constants section */
  23. /*-----------------------------------------------------------------*/
  24.  
  25.  
  26. /*-----------------------------------------------------------------*/
  27. void lib_output_comment (char *comment)
  28. {
  29.     switch (gRT_out_format) {
  30.  
  31.     case OUTPUT_VIDEO:
  32.     case OUTPUT_DELAYED:
  33.     case OUTPUT_RAWTRI:
  34.     case OUTPUT_DXF:    /* well, there's the 999 format, but... >>>>> */
  35.         /* no comments allowed for these file formats */
  36.         break;
  37.  
  38.     case OUTPUT_NFF:
  39.     case OUTPUT_OBJ:
  40.     case OUTPUT_RIB:
  41.         fprintf(gOutfile, "# %s\n", comment);
  42.         break;
  43.  
  44.     case OUTPUT_RAYSHADE:
  45.     case OUTPUT_POLYRAY:
  46.     case OUTPUT_POVRAY_10:
  47.     case OUTPUT_POVRAY_20:
  48.         fprintf(gOutfile, "// %s\n", comment);
  49.         break;
  50.  
  51.     /* unknown comment formats... whoever knows, please fix or fill in! */
  52.     case OUTPUT_PLG:
  53.     case OUTPUT_VIVID:
  54.     case OUTPUT_RTRACE:
  55.     case OUTPUT_QRT:
  56.     case OUTPUT_ART:
  57.     default:
  58.         fprintf(gOutfile, "// <comment> '%s'\n", comment);
  59.         break;
  60.  
  61.     }
  62. } /* lib_output_comment */
  63.  
  64.  
  65. /*-----------------------------------------------------------------*/
  66. void lib_output_vector(x, y, z)
  67. double    x, y, z;
  68. {
  69.     switch (gRT_out_format) {
  70.     case OUTPUT_VIDEO:
  71.     case OUTPUT_DELAYED:
  72.     case OUTPUT_DXF:
  73.         break;
  74.  
  75.     case OUTPUT_PLG:
  76.     case OUTPUT_OBJ:
  77.     case OUTPUT_NFF:
  78.     case OUTPUT_VIVID:
  79.     case OUTPUT_RAYSHADE:
  80.     case OUTPUT_RTRACE:
  81.     case OUTPUT_RAWTRI:
  82.         fprintf(gOutfile, "%g %g %g", x, y, z);
  83.         break;
  84.  
  85.     case OUTPUT_POVRAY_10:
  86.         fprintf(gOutfile, "<%g %g %g>", x, y, z);
  87.         break;
  88.     case OUTPUT_POVRAY_20:
  89.         fprintf(gOutfile, "<%g, %g, %g>", x, y, z);
  90.         break;
  91.  
  92.     case OUTPUT_POLYRAY:
  93.     case OUTPUT_QRT:
  94.     case OUTPUT_ART:
  95.         fprintf(gOutfile, "%g, %g, %g", x, y, z);
  96.         break;
  97.     }
  98. } /* lib_output_vector */
  99.  
  100.  
  101.  
  102. /*-----------------------------------------------------------------*/
  103. void
  104. axis_to_z(axis, xang, yang)
  105.      COORD3 axis;
  106.      double *xang, *yang;
  107. {
  108.   double len;
  109.  
  110.   /* The axis is in RH coordinates and turns the axis to Z axis */
  111.   /* The angles are for the LH coordinate system */
  112.   len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  113.   *xang = -180.0 * asin(axis[Y]) / PI;
  114.   if (len < EPSILON)
  115.     *yang = 0.0;
  116.   else
  117.     *yang = 180.0 * acos(axis[Z] / len) / PI;
  118.   if (axis[X] < 0)
  119.     *yang = -(*yang);
  120. } /* axis_to_z */
  121.  
  122. /*-----------------------------------------------------------------*/
  123. /*
  124.  * Output viewpoint location.  The parameters are:
  125.  *   From:   The eye location.
  126.  *   At:     A position to be at the center of the image.  A.k.a. "lookat"
  127.  *   Up:     A vector defining which direction is up.
  128.  *   Fov:    Vertical field of view of the camera
  129.  *   Aspect: Aspect ratio of horizontal fov to vertical fov
  130.  *   Hither: Minimum distance to any ray-surface intersection
  131.  *   Resx:   X resolution of resulting image
  132.  *   Resy:   Y resolution of resulting image
  133.  *
  134.  * For all databases some viewing parameters are always the same:
  135.  *
  136.  *   Viewing angle is defined as from the center of top pixel row to bottom
  137.  *     pixel row and left column to right column.
  138.  *   Yon is "at infinity."
  139.  */
  140. void
  141. lib_output_viewpoint(from, at, up,
  142.              fov_angle, aspect_ratio, hither,
  143.              resx, resy)
  144.     COORD3 from, at, up;
  145.     double fov_angle, aspect_ratio, hither;
  146.     int    resx, resy;
  147. {
  148.     COORD3 axis, myup1, myup, myright, tmp;
  149.     COORD4 viewvec, rightvec;
  150.     MATRIX m1;
  151.     double twist, xang, yang, len, tmpf;
  152.     double frustrumheight, frustrumwidth;
  153.  
  154.     switch (gRT_out_format) {
  155.     case OUTPUT_DELAYED:
  156.     case OUTPUT_VIDEO:
  157.     case OUTPUT_PLG:
  158.     case OUTPUT_OBJ:
  159.         /* Save the various view parameters */
  160.         COPY_COORD3(gViewpoint.from, from);
  161.         COPY_COORD3(gViewpoint.at, at);
  162.         COPY_COORD3(gViewpoint.up, up);
  163.         gViewpoint.angle  = fov_angle;
  164.         gViewpoint.hither = hither;
  165.         gViewpoint.resx   = resx;
  166.         gViewpoint.resy   = resy;
  167.         gViewpoint.aspect = aspect_ratio;
  168.  
  169.         /* Make the 3D clipping box for this view */
  170.         gView_bounds[0][0] = -gViewpoint.resx/2;
  171.         gView_bounds[1][0] =  gViewpoint.resx/2;
  172.         gView_bounds[0][1] = -gViewpoint.resy/2;
  173.         gView_bounds[1][1] =  gViewpoint.resy/2;
  174.         gView_bounds[0][2] =  gViewpoint.hither;
  175.         gView_bounds[1][2] = 1.0e10;
  176.  
  177.         /* Generate the perspective view matrix */
  178.         lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  179.                    gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  180.                    gViewpoint.angle, gViewpoint.aspect);
  181.  
  182.         /* Turn on graphics using system dependent video routines */
  183.         if (gRT_out_format == OUTPUT_VIDEO) {
  184.         display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  185.         gView_init_flag = 1;
  186.         }
  187.         break;
  188.  
  189.     case OUTPUT_NFF:
  190.         fprintf(gOutfile, "v\n");
  191.         fprintf(gOutfile, "from %g %g %g\n", from[X], from[Y], from[Z]);
  192.         fprintf(gOutfile, "at %g %g %g\n", at[X], at[Y], at[Z]);
  193.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  194.         fprintf(gOutfile, "angle %g\n", fov_angle);
  195.         fprintf(gOutfile, "hither %g\n", hither);
  196.         fprintf(gOutfile, "resolution %d %d\n", resx, resy);
  197.         break;
  198.  
  199.     case OUTPUT_POVRAY_10:
  200.     case OUTPUT_POVRAY_20:
  201.         /* Let's get a set of vectors that are all at right angles to each
  202.            other that describe the view given. */
  203.         lib_normalize_vector(up);
  204.         SUB3_COORD3(viewvec, at, from);
  205.         lib_normalize_vector(viewvec);
  206.         CROSS(rightvec, up, viewvec);
  207.         lib_normalize_vector(rightvec);
  208.         CROSS(up, viewvec, rightvec);
  209.         lib_normalize_vector(up);
  210.  
  211.         /* Calculate the height of the view frustrum in world coordinates.
  212.            and then scale the right and up vectors appropriately. */
  213.         frustrumheight = 2.0 * tan(PI * fov_angle / 360.0);
  214.         frustrumwidth = aspect_ratio * frustrumheight;
  215.         up[X] *= frustrumheight;
  216.         up[Y] *= frustrumheight;
  217.         up[Z] *= frustrumheight;
  218.         rightvec[X] *= frustrumwidth;
  219.         rightvec[Y] *= frustrumwidth;
  220.         rightvec[Z] *= frustrumwidth;
  221.  
  222.         tab_indent();
  223.         fprintf(gOutfile, "camera {\n");
  224.         tab_inc();
  225.  
  226.         if (gRT_out_format == OUTPUT_POVRAY_10) {
  227.         tab_indent();
  228.         fprintf(gOutfile, "location <%g %g %g>\n",
  229.             from[X], from[Y], from[Z]);
  230.         tab_indent();
  231.         fprintf(gOutfile, "direction <%g %g %g>\n",
  232.             viewvec[X], viewvec[Y], viewvec[Z]);
  233.         tab_indent();
  234.         fprintf(gOutfile, "right <%g %g %g>\n",
  235.             rightvec[X], rightvec[Y], rightvec[Z]);
  236.         tab_indent();
  237.         fprintf(gOutfile, "up <%g %g %g>\n",
  238.             up[X], up[Y], up[Z]);
  239.         }
  240.         else {
  241.         tab_indent();
  242.         fprintf(gOutfile, "location <%g, %g, %g>\n",
  243.             from[X], from[Y], from[Z]);
  244.         tab_indent();
  245.         fprintf(gOutfile, "direction <%g, %g, %g>\n",
  246.             viewvec[X], viewvec[Y], viewvec[Z]);
  247.         tab_indent();
  248.         fprintf(gOutfile, "right <%g, %g, %g>\n",
  249.             rightvec[X], rightvec[Y], rightvec[Z]);
  250.         tab_indent();
  251.         fprintf(gOutfile, "up <%g, %g, %g>\n",
  252.             up[X], up[Y], up[Z]);
  253.         }
  254.         tab_dec();
  255.         fprintf(gOutfile, "} // camera\n");
  256.         fprintf(gOutfile, "\n");
  257.         break;
  258.  
  259.     case OUTPUT_POLYRAY:
  260.         tab_indent();
  261.         fprintf(gOutfile, "viewpoint {\n");
  262.         tab_inc();
  263.  
  264.         tab_indent();
  265.         fprintf(gOutfile, "from <%g, %g, %g>\n", from[X], from[Y], from[Z]);
  266.         tab_indent();
  267.         fprintf(gOutfile, "at <%g, %g, %g>\n", at[X], at[Y], at[Z]);
  268.         tab_indent();
  269.         fprintf(gOutfile, "up <%g, %g, %g>\n", up[X], up[Y], up[Z]);
  270.         tab_indent();
  271.         fprintf(gOutfile, "angle %g\n", fov_angle);
  272.         tab_indent();
  273.         fprintf(gOutfile, "aspect %g\n", aspect_ratio);
  274.         tab_indent();
  275.         fprintf(gOutfile, "hither %g\n", hither);
  276.         tab_indent();
  277.         fprintf(gOutfile, "resolution %d, %d\n", resx, resy);
  278.  
  279.         tab_dec();
  280.         tab_indent();
  281.         fprintf(gOutfile, "}\n");
  282.         fprintf(gOutfile, "\n");
  283.         break;
  284.  
  285.     case OUTPUT_VIVID:
  286.         tab_indent();
  287.         fprintf(gOutfile, "studio {\n");
  288.         tab_inc();
  289.  
  290.         tab_indent();
  291.         fprintf(gOutfile, "from %g %g %g\n", from[X], from[Y], from[Z]);
  292.         tab_indent();
  293.         fprintf(gOutfile, "at %g %g %g\n", at[X], at[Y], at[Z]);
  294.         tab_indent();
  295.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  296.         tab_indent();
  297.         fprintf(gOutfile, "angle %g\n", fov_angle);
  298.         tab_indent();
  299.         fprintf(gOutfile, "aspect %g\n", aspect_ratio);
  300.         tab_indent();
  301.         fprintf(gOutfile, "resolution %d %d\n", resx, resy);
  302.         tab_indent();
  303.         fprintf(gOutfile, "no_exp_trans\n");
  304.  
  305.         tab_dec();
  306.         tab_indent();
  307.         fprintf(gOutfile, "}\n");
  308.         fprintf(gOutfile, "\n");
  309.         break;
  310.  
  311.     case OUTPUT_QRT:
  312.         tab_indent();
  313.         fprintf(gOutfile, "OBSERVER = (\n");
  314.         tab_inc();
  315.  
  316.         tab_indent();
  317.         fprintf(gOutfile, "loc = (%g,%g,%g),\n", from[X], from[Y], from[Z]);
  318.         tab_indent();
  319.         fprintf(gOutfile, "lookat = (%g,%g,%g),\n", at[X], at[Y], at[Z]);
  320.         tab_indent();
  321.         fprintf(gOutfile, "up = (%g,%g,%g)\n", up[X], up[Y], up[Z]);
  322.         tab_dec();
  323.         tab_indent();
  324.         fprintf(gOutfile, ")\n");
  325.  
  326.         tab_indent();
  327.         fprintf(gOutfile, "FOC_LENGTH = %g\n",
  328.             35.0 / tan(PI * fov_angle / 360.0));
  329.         tab_indent();
  330.         fprintf(gOutfile, "DEFAULT (\n");
  331.         tab_inc();
  332.         tab_indent();
  333.         fprintf(gOutfile, "aspect = %g,\n", 6.0 * aspect_ratio / 7.0);
  334.         tab_indent();
  335.         fprintf(gOutfile, "x_res = %d, y_res = %d\n", resx, resy);
  336.         tab_dec();
  337.         tab_indent();
  338.         fprintf(gOutfile, ")\n");
  339.  
  340.         /* QRT insists on having the output file as part of the data text */
  341.         tab_indent();
  342.         fprintf(gOutfile, "FILE_NAME = qrt.tga\n");
  343.         break;
  344.  
  345.     case OUTPUT_RAYSHADE:
  346.         fprintf(gOutfile, "eyep %g %g %g\n", from[X], from[Y], from[Z]);
  347.         fprintf(gOutfile, "lookp %g %g %g\n", at[X], at[Y], at[Z]);
  348.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  349.         fprintf(gOutfile, "fov %g %g\n", aspect_ratio * fov_angle,
  350.              fov_angle);
  351.         fprintf(gOutfile, "screen %d %d\n", resx, resy);
  352.         fprintf(gOutfile, "sample 1 nojitter\n");
  353.         break;
  354.  
  355.     case OUTPUT_RTRACE:
  356.         fprintf(gOutfile, "View\n");
  357.         fprintf(gOutfile, "%g %g %g\n", from[X], from[Y], from[Z]);
  358.         fprintf(gOutfile, "%g %g %g\n", at[X], at[Y], at[Z]);
  359.         fprintf(gOutfile, "%g %g %g\n", up[X], up[Y], up[Z]);
  360.         fprintf(gOutfile, "%g %g\n", aspect_ratio * fov_angle/2,
  361.              fov_angle/2);
  362.         break;
  363.  
  364.     case OUTPUT_ART:
  365.         fprintf(gOutfile, "maxhitlevel 4\n");
  366.         fprintf(gOutfile, "screensize 0.0, 0.0\n");
  367.         fprintf(gOutfile, "fieldofview %g\n", fov_angle);
  368.         fprintf(gOutfile, "up(%g, %g, %g)\n", up[X], up[Y], up[Z]);
  369.         fprintf(gOutfile, "lookat(%g, %g, %g, ", from[X], from[Y], from[Z]);
  370.         fprintf(gOutfile, "%g, %g, %g, 0.0)\n", at[X], at[Y], at[Z]);
  371.         fprintf(gOutfile, "\n");
  372.         break;
  373.  
  374.     case OUTPUT_RAWTRI:
  375.         break;
  376.  
  377.     case OUTPUT_RIB:
  378.         fprintf(gOutfile, "version 3.03\n");
  379.         fprintf(gOutfile, "FrameBegin 1\n");
  380.         fprintf(gOutfile, "Format %d %d 1\n", resx, resy);
  381.         fprintf(gOutfile, "PixelSamples 1 1\n");
  382.         fprintf(gOutfile, "ShadingRate 1.0\n");
  383.         fprintf(gOutfile, "Projection \"perspective\" \"fov\" %#g\n",
  384.             fov_angle);
  385.         fprintf(gOutfile, "Clipping %#g %#g\n\n", hither, 1e38);
  386.  
  387.         /* Calculate transformation from intrisic position */
  388.         SUB3_COORD3(axis, at, from);
  389.         lib_normalize_vector(axis);
  390.  
  391.         COPY_COORD3(tmp,axis);
  392.         tmpf = DOT_PRODUCT(up,axis);
  393.         tmp[0] *= tmpf;  tmp[1] *= tmpf;  tmp[2] *= tmpf;
  394.         SUB2_COORD3(up,tmp);
  395.         lib_normalize_vector(up);
  396.  
  397.         CROSS(myright,up,axis);
  398.         lib_normalize_vector (myright);
  399.  
  400.         m1[0][0] = myright[0];  m1[1][0] = myright[1];
  401.         m1[2][0] = myright[2];  m1[3][0] = 0;
  402.         m1[0][1] = up[0];  m1[1][1] = up[1];
  403.         m1[2][1] = up[2]; m1[3][1] = 0;
  404.         m1[0][2] = axis[0];  m1[1][2] = axis[1];
  405.         m1[2][2] = axis[2];  m1[3][2] = 0;
  406.         m1[0][3] = 0;  m1[1][3] = 0;  m1[2][3] = 0;  m1[3][3] = 1;
  407.         fprintf (gOutfile, "ConcatTransform [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g]\n",
  408.              m1[0][0], m1[0][1], m1[0][2], m1[0][3],
  409.              m1[1][0], m1[1][1], m1[1][2], m1[1][3],
  410.              m1[2][0], m1[2][1], m1[2][2], m1[2][3],
  411.              m1[3][0], m1[3][1], m1[3][2], m1[3][3]);
  412.         fprintf (gOutfile, "Translate %g %g %g\n", -from[0], -from[1], -from[2]);
  413.  
  414.         fprintf(gOutfile, "WorldBegin\n");
  415.         tab_inc();
  416.         break ;
  417.  
  418.     case OUTPUT_DXF:
  419.         fprintf(gOutfile, "  0\n" ) ;
  420.         fprintf(gOutfile, "SECTION\n" ) ;
  421.         fprintf(gOutfile, "  2\n" ) ;
  422.         fprintf(gOutfile, "HEADER\n" ) ;
  423.         fprintf(gOutfile, "  0\n" ) ;
  424.         fprintf(gOutfile, "ENDSEC\n" ) ;
  425.         fprintf(gOutfile, "  0\n" ) ;
  426.         fprintf(gOutfile, "SECTION\n" ) ;
  427.         fprintf(gOutfile, "  2\n" ) ;
  428.         fprintf(gOutfile, "ENTITIES\n" ) ;
  429.         /* should add view someday ... */
  430.         break;
  431.     }
  432. }
  433.  
  434. /*-----------------------------------------------------------------*/
  435. /*
  436.  * Output light.  A light is defined by position.  All lights have the same
  437.  * intensity.
  438.  *
  439.  */
  440. void
  441. lib_output_light(center_pt)
  442.     COORD4 center_pt;
  443. {
  444.     double lscale;
  445.     light_ptr new_light;
  446.  
  447.     if (center_pt[W] != 0.0)
  448.     lscale = center_pt[W];
  449.     else
  450.     lscale = 1.0;
  451.  
  452.     switch (gRT_out_format) {
  453.     case OUTPUT_DELAYED:
  454.         new_light = (light_ptr)malloc(sizeof(struct light_struct));
  455.         if (new_light == NULL)
  456.            /* Quietly fail & return */
  457.            return;
  458.         COPY_COORD4(new_light->center_pt, center_pt);
  459.         new_light->center_pt[W] = lscale;
  460.         new_light->next = gLib_lights;
  461.         gLib_lights = new_light;
  462.         break;
  463.  
  464.     case OUTPUT_VIDEO:
  465.     case OUTPUT_PLG:
  466.     case OUTPUT_OBJ:
  467.         /* Not currently doing anything with lights */
  468.         break;
  469.  
  470.     case OUTPUT_NFF:
  471.         fprintf(gOutfile, "l %g %g %g\n",
  472.             center_pt[X], center_pt[Y], center_pt[Z]);
  473.         break;
  474.  
  475.     case OUTPUT_POVRAY_10:
  476.         tab_indent();
  477.         fprintf(gOutfile, "object {\n");
  478.         tab_inc();
  479.  
  480.         tab_indent();
  481.         fprintf(gOutfile, "light_source {\n");
  482.         tab_inc();
  483.  
  484.         tab_indent();
  485.         fprintf(gOutfile, "<%g %g %g>",
  486.             center_pt[X], center_pt[Y], center_pt[Z]);
  487.         fprintf(gOutfile, " color red %g green %g blue %g\n",
  488.             lscale, lscale, lscale);
  489.  
  490.         tab_dec();
  491.         tab_indent();
  492.         fprintf(gOutfile, "} // light\n");
  493.  
  494.         tab_dec();
  495.         tab_indent();
  496.         fprintf(gOutfile, "} // object\n");
  497.  
  498.         fprintf(gOutfile, "\n");
  499.         break;
  500.  
  501.     case OUTPUT_POVRAY_20:
  502.         tab_indent();
  503.         fprintf(gOutfile, "light_source {\n");
  504.         tab_inc();
  505.  
  506.         tab_indent();
  507.         fprintf(gOutfile, "<%g, %g, %g>",
  508.             center_pt[X], center_pt[Y], center_pt[Z]);
  509.         fprintf(gOutfile, " color red %g green %g blue %g\n",
  510.             lscale, lscale, lscale);
  511.  
  512.         tab_dec();
  513.         tab_indent();
  514.         fprintf(gOutfile, "} // light\n");
  515.  
  516.         fprintf(gOutfile, "\n");
  517.         break;
  518.  
  519.     case OUTPUT_POLYRAY:
  520.         tab_indent();
  521.         fprintf(gOutfile, "light <%g, %g, %g>, <%g, %g, %g>\n",
  522.             lscale, lscale, lscale,
  523.             center_pt[X], center_pt[Y], center_pt[Z]);
  524.         fprintf(gOutfile, "\n");
  525.         break;
  526.  
  527.     case OUTPUT_VIVID:
  528.         tab_indent();
  529.         fprintf(gOutfile, "light {type point position %g %g %g",
  530.             center_pt[X], center_pt[Y], center_pt[Z]);
  531.         fprintf(gOutfile, " color %g %g %g }\n",
  532.             lscale, lscale, lscale);
  533.         fprintf(gOutfile, "\n");
  534.         break;
  535.  
  536.     case OUTPUT_QRT:
  537.         tab_indent();
  538.         fprintf(gOutfile, "LAMP ( loc = (%g,%g,%g), dist = 0, radius = 1,",
  539.             center_pt[X], center_pt[Y], center_pt[Z]);
  540.         fprintf(gOutfile, " amb = (%g,%g,%g) )\n",
  541.             lscale, lscale, lscale);
  542.         break;
  543.  
  544.     case OUTPUT_RAYSHADE:
  545.         fprintf(gOutfile, "light %g point %g %g %g\n",
  546.             center_pt[W], center_pt[X], center_pt[Y], center_pt[Z]);
  547.         break;
  548.  
  549.     case OUTPUT_RTRACE:
  550.         fprintf(gOutfile, "1 %g %g %g %g %g %g\n",
  551.         center_pt[X], center_pt[Y], center_pt[Z],
  552.         center_pt[W], center_pt[W], center_pt[W]);
  553.         break;
  554.  
  555.     case OUTPUT_ART:
  556.         tab_indent();
  557.         fprintf(gOutfile, "light \n{");
  558.         tab_inc();
  559.  
  560.         tab_indent();
  561.         fprintf(gOutfile, "location(%g, %g, %g)  colour 0.5, 0.5, 0.5\n",
  562.            center_pt[X], center_pt[Y], center_pt[Z]);
  563.  
  564.         tab_dec();
  565.         tab_indent();
  566.         fprintf(gOutfile, "}\n");
  567.         fprintf(gOutfile, "\n");
  568.         break;
  569.  
  570.     case OUTPUT_RAWTRI:
  571.     case OUTPUT_DXF:
  572.         break;
  573.  
  574.     case OUTPUT_RIB:
  575.       {
  576.         static int number= 0;
  577.  
  578.         fprintf(gOutfile, "LightSource \"pointlight\" %d"
  579.             " \"from\" [ %#g %#g %#g ] \"intensity\" [20]\n", number++,
  580.             center_pt[X], center_pt[Y], center_pt[Z]);
  581.       }
  582.         break;
  583.     }
  584. }
  585.  
  586. /*-----------------------------------------------------------------*/
  587. /*
  588.  * Output background color.  A color is simply RGB (monitor dependent, but
  589.  * that's life).
  590.  */
  591. void
  592. lib_output_background_color(color)
  593.     COORD3 color;
  594. {
  595.     switch (gRT_out_format) {
  596.     case OUTPUT_VIDEO:
  597.     case OUTPUT_DELAYED:
  598.     case OUTPUT_PLG:
  599.     case OUTPUT_OBJ:
  600.         COPY_COORD3(gBkgnd_color, color);
  601.         break;
  602.  
  603.     case OUTPUT_NFF:
  604.         fprintf(gOutfile, "b %g %g %g\n", color[X], color[Y], color[Z]);
  605.         break;
  606.  
  607.     case OUTPUT_POVRAY_10:
  608.         /* POV-Ray 1.0 does not support a background color */
  609.         /* Instead, create arbitrarily large enclosing sphere of that
  610.          * color */
  611.         tab_indent();
  612.         fprintf(gOutfile, "// background color:\n");
  613.  
  614.         tab_indent();
  615.         fprintf(gOutfile, "object {\n");
  616.         tab_inc();
  617.  
  618.         tab_indent();
  619.         fprintf(gOutfile, "sphere { <0 0 0> 9000  ");
  620.         fprintf(gOutfile,
  621.         "texture { ambient 1 diffuse 0 color red %g green %g blue %g } }\n",
  622.                color[X], color[Y], color[Z]);
  623.         tab_dec();
  624.         tab_indent();
  625.         fprintf(gOutfile, "} // object - background\n");
  626.         fprintf(gOutfile, "\n");
  627.         break;
  628.  
  629.     case OUTPUT_POVRAY_20:
  630.         tab_indent();
  631.         fprintf(gOutfile, "background { color red %g green %g blue %g }\n",
  632.            color[X], color[Y], color[Z]);
  633.         fprintf(gOutfile, "\n");
  634.         break;
  635.  
  636.     case OUTPUT_POLYRAY:
  637.         tab_indent();
  638.         fprintf(gOutfile, "background <%g, %g, %g>\n",
  639.             color[X], color[Y], color[Z]);
  640.         fprintf(gOutfile, "\n");
  641.         break;
  642.  
  643.     case OUTPUT_VIVID:
  644.         /* Vivid insists on putting the background into the studio */
  645.         tab_indent();
  646.         fprintf(gOutfile, "studio { background %g %g %g }\n",
  647.             color[X], color[Y], color[Z]);
  648.         fprintf(gOutfile, "\n");
  649.         break;
  650.  
  651.     case OUTPUT_QRT:
  652.         tab_indent();
  653.         fprintf(gOutfile, "SKY ( horiz = (%g,%g,%g), zenith = (%g,%g,%g),",
  654.             color[X], color[Y], color[Z],
  655.             color[X], color[Y], color[Z]);
  656.         fprintf(gOutfile, " dither = 0 )\n");
  657.         break;
  658.  
  659.     case OUTPUT_RAYSHADE:
  660.         fprintf(gOutfile, "background %g %g %g\n",
  661.             color[X], color[Y], color[Z]);
  662.         break;
  663.  
  664.     case OUTPUT_RTRACE:
  665.         fprintf(gOutfile, "Colors\n");
  666.         fprintf(gOutfile, "%g %g %g\n", color[X], color[Y], color[Z]);
  667.         fprintf(gOutfile, "0 0 0\n");
  668.         break;
  669.  
  670.     case OUTPUT_RAWTRI:
  671.     case OUTPUT_DXF:
  672.         break;
  673.  
  674.     case OUTPUT_ART:
  675.         tab_indent();
  676.         fprintf(gOutfile, "background %g, %g, %g\n",
  677.             color[X], color[Y], color[Z]);
  678.         fprintf(gOutfile, "\n");
  679.         break;
  680.       case OUTPUT_RIB:
  681.         fprintf(gOutfile, "# Background color [%#g %#g %#g]\n",
  682.             color[X], color[Y], color[Z]);
  683.         break;
  684.  
  685.     }
  686. }
  687.  
  688. /*-----------------------------------------------------------------*/
  689. static char *
  690. create_surface_name(name, val)
  691.     char *name;
  692.     int val;
  693. {
  694.     char *txname;
  695.  
  696.     if (name != NULL)
  697.     return name;
  698.  
  699.     txname = (char *)malloc(7*sizeof(char));
  700.     if (txname == NULL)
  701.     return NULL;
  702.     sprintf(txname, "txt%03d", val);
  703.     txname[6] = '\0';
  704.     return txname;
  705. }
  706.  
  707. /*-----------------------------------------------------------------*/
  708. /*
  709.  * Output color and shading parameters for all following objects
  710.  *
  711.  * For POV-Ray and Polyray, a character string will be returned that
  712.  * identified this texture.  The default texture will be updated with
  713.  * the name generated by this function.
  714.  *
  715.  * Meaning of the color and shading parameters:
  716.  *    name   = name that this surface can be referenced by...
  717.  *    color  = surface color
  718.  *    ka     = ambient component
  719.  *    kd     = diffuse component
  720.  *    ks     = amount contributed from the reflected direction
  721.  *    shine  = contribution from specular highlights
  722.  *    ang    = angle at which the specular highlight falls to 50% of maximum
  723.  *    t      = amount from the refracted direction
  724.  *    i_of_r = index of refraction of the surface
  725.  *
  726.  */
  727. char *
  728. lib_output_color(name, color, ka, kd, ks, shine, ang, kt, i_of_r)
  729.     char *name;
  730.     COORD3 color;
  731.     double ka, kd, ks, shine, ang, kt, i_of_r;
  732. {
  733.     surface_ptr new_surf;
  734.     char *txname = NULL;
  735.     double phong_pow;
  736.  
  737.     /* Increment the number of surface types we know about */
  738.     ++gTexture_count;
  739.     gTexture_ior = i_of_r;
  740.  
  741.     /* Calculate the Phong coefficient */
  742.     phong_pow = PI * ang / 180.0;
  743.     if (phong_pow <= 0.0)
  744.     phong_pow = 100000.0;
  745.     else if (phong_pow >= (PI/4.0))
  746.     phong_pow = 0.000001;
  747.     else
  748.     phong_pow = -(log(2.0) / log(cos(2.0 * phong_pow)));
  749.  
  750.     switch (gRT_out_format) {
  751.     case OUTPUT_DELAYED:
  752.         new_surf = (surface_ptr)malloc(sizeof(struct surface_struct));
  753.         if (new_surf == NULL)
  754.            /* Quietly fail */
  755.         return NULL;
  756.         new_surf->surf_name = create_surface_name(name, gTexture_count);
  757.         new_surf->surf_index = gTexture_count;
  758.         COPY_COORD3(new_surf->color, color);
  759.         new_surf->ka = ka;
  760.         new_surf->kd = kd;
  761.         new_surf->ks = ks;
  762.         new_surf->shine = shine;
  763.         new_surf->ang = ang;
  764.         new_surf->kt = kt;
  765.         new_surf->ior = i_of_r;
  766.         new_surf->next = gLib_surfaces;
  767.         gLib_surfaces = new_surf;
  768.         break;
  769.  
  770.     case OUTPUT_PLG:
  771.     case OUTPUT_VIDEO:
  772.         COPY_COORD3(gFgnd_color, color);
  773.         break;
  774.  
  775.     case OUTPUT_NFF:
  776.         fprintf(gOutfile, "f %g %g %g %g %g %g %g %g\n",
  777.         color[X], color[Y], color[Z], kd, ks, phong_pow, kt, i_of_r);
  778.         break;
  779.  
  780.     case OUTPUT_POVRAY_10:
  781.         txname = create_surface_name(name, gTexture_count);
  782.         tab_indent();
  783.         fprintf(gOutfile, "#declare %s = texture {\n", txname);
  784.         tab_inc();
  785.  
  786.         tab_indent();
  787.         fprintf(gOutfile, "color red %g green %g blue %g",
  788.             color[X], color[Y], color[Z]);
  789.         if (kt > 0)
  790.         fprintf(gOutfile, " alpha %g", kt);
  791.         fprintf(gOutfile, "\n");
  792.  
  793.         tab_indent();
  794.         fprintf(gOutfile, "ambient %g\n", ka);
  795.  
  796.         tab_indent();
  797.         fprintf(gOutfile, "diffuse %g\n", kd);
  798.  
  799.         if (shine != 0) {
  800.         tab_indent();
  801.         fprintf(gOutfile, "phong %g phong_size %g\n", shine, phong_pow);
  802.         }
  803.  
  804.         if (ks != 0) {
  805.         tab_indent();
  806.         fprintf(gOutfile, "reflection %g\n", ks);
  807.         }
  808.  
  809.         if (kt != 0) {
  810.         tab_indent();
  811.         fprintf(gOutfile, "refraction 1.0 ior %g\n", i_of_r);
  812.         }
  813.  
  814.         tab_dec();
  815.         tab_indent();
  816.         fprintf(gOutfile, "} // texture %s\n", txname);
  817.         fprintf(gOutfile, "\n");
  818.         break;
  819.  
  820.     case OUTPUT_POVRAY_20:
  821.         txname = create_surface_name(name, gTexture_count);
  822.         tab_indent();
  823.         fprintf(gOutfile, "#declare %s = texture {\n", txname);
  824.         tab_inc();
  825.  
  826.         tab_indent();
  827.         fprintf(gOutfile, "pigment {\n");
  828.         tab_inc();
  829.  
  830.         tab_indent();
  831.         fprintf(gOutfile, "color red %g green %g blue %g",
  832.             color[X], color[Y], color[Z]);
  833.         if (kt > 0)
  834.         fprintf(gOutfile, " filter %g", kt);
  835.         fprintf(gOutfile, "\n");
  836.  
  837.         tab_dec();
  838.         tab_indent();
  839.         fprintf(gOutfile, "} // pigment\n");
  840.  
  841.         tab_indent();
  842.         fprintf(gOutfile, "// normal { bumps, ripples, etc. }\n");
  843.  
  844.         tab_indent();
  845.         fprintf(gOutfile, "finish {\n");
  846.         tab_inc();
  847.  
  848.         tab_indent();
  849.         fprintf(gOutfile, "ambient %g\n", ka);
  850.  
  851.         tab_indent();
  852.         fprintf(gOutfile, "diffuse %g\n", kd);
  853.  
  854.         if (shine != 0) {
  855.         tab_indent();
  856.         fprintf(gOutfile, "phong %g  phong_size %g\n", shine, phong_pow);
  857.         }
  858.  
  859.         if (ks != 0) {
  860.         tab_indent();
  861.         fprintf(gOutfile, "reflection %g\n", ks);
  862.         }
  863.  
  864.         if (kt != 0) {
  865.         tab_indent();
  866.         fprintf(gOutfile, "refraction 1.0 ior %g\n", i_of_r);
  867.         }
  868.  
  869.         tab_dec();
  870.         tab_indent();
  871.         fprintf(gOutfile, "} // finish\n");
  872.  
  873.         tab_dec();
  874.         tab_indent();
  875.         fprintf(gOutfile, "} // texture %s\n", txname);
  876.         fprintf(gOutfile, "\n");
  877.         break;
  878.  
  879.     case OUTPUT_POLYRAY:
  880.         txname = create_surface_name(name, gTexture_count);
  881.         tab_indent();
  882.         fprintf(gOutfile, "define %s\n", txname);
  883.  
  884.         tab_indent();
  885.         fprintf(gOutfile, "texture {\n");
  886.         tab_inc();
  887.  
  888.         tab_indent();
  889.         fprintf(gOutfile, "surface {\n");
  890.         tab_inc();
  891.  
  892.         tab_indent();
  893.         fprintf(gOutfile, "ambient <%g, %g, %g>, %g\n",
  894.            color[X], color[Y], color[Z], ka);
  895.  
  896.         tab_indent();
  897.         fprintf(gOutfile, "diffuse <%g, %g, %g>, %g\n",
  898.            color[X], color[Y], color[Z], kd);
  899.  
  900.         if (shine != 0) {
  901.         tab_indent();
  902.         fprintf(gOutfile, "specular white, %g\n", shine);
  903.         tab_indent();
  904.         fprintf(gOutfile, "microfacet Phong %g\n", ang);
  905.         }
  906.  
  907.         if (ks != 0) {
  908.         tab_indent();
  909.         fprintf(gOutfile, "reflection white, %g\n", ks);
  910.         }
  911.  
  912.         if (kt != 0) {
  913.         tab_indent();
  914.         fprintf(gOutfile, "transmission white, %g, %g\n", kt, i_of_r);
  915.         }
  916.  
  917.         tab_dec();
  918.         tab_indent();
  919.         fprintf(gOutfile, "}\n");
  920.  
  921.         tab_dec();
  922.         tab_indent();
  923.         fprintf(gOutfile, "}\n");
  924.         fprintf(gOutfile, "\n");
  925.         break;
  926.  
  927.     case OUTPUT_VIVID:
  928.         tab_indent();
  929.         fprintf(gOutfile, "surface {\n");
  930.         tab_inc();
  931.  
  932.         tab_indent();
  933.         fprintf(gOutfile, "ambient %g %g %g\n",
  934.             ka * color[X], ka * color[Y], ka * color[Z], ka);
  935.  
  936.         tab_indent();
  937.         fprintf(gOutfile, "diffuse %g %g %g\n",
  938.             kd * color[X], kd * color[Y], kd * color[Z], ka);
  939.  
  940.         if (shine != 0) {
  941.         tab_indent();
  942.         fprintf(gOutfile, "shine %g %g %g %g\n",
  943.                phong_pow, shine, shine, shine);
  944.         }
  945.         if (ks != 0) {
  946.         tab_indent();
  947.         fprintf(gOutfile, "specular %g %g %g\n", ks, ks, ks);
  948.         }
  949.         if (kt != 0) {
  950.         tab_indent();
  951.         fprintf(gOutfile, "transparent %g %g %g\n",
  952.              kt * color[X], kt * color[Y], kt * color[Z]);
  953.         tab_indent();
  954.         fprintf(gOutfile, "ior %g\n", i_of_r);
  955.         }
  956.  
  957.         tab_dec();
  958.         tab_indent();
  959.         fprintf(gOutfile, "}\n");
  960.         fprintf(gOutfile, "\n");
  961.         break;
  962.  
  963.     case OUTPUT_QRT:
  964.         tab_indent();
  965.         fprintf(gOutfile, "DEFAULT (\n");
  966.         tab_inc();
  967.  
  968.         tab_indent();
  969.         fprintf(gOutfile, "amb = (%g,%g,%g),\n",
  970.             ka * color[X], ka * color[Y], ka * color[Z], ka);
  971.         tab_indent();
  972.         fprintf(gOutfile, "diff = (%g,%g,%g),\n",
  973.             kd * color[X], kd * color[Y], kd * color[Z], ka);
  974.         tab_indent();
  975.         fprintf(gOutfile, "reflect = %g, sreflect = %g,\n",
  976.             shine, phong_pow);
  977.         tab_indent();
  978.         fprintf(gOutfile, "mirror = (%g,%g,%g),\n",
  979.             ks * color[X], ks * color[Y], ks * color[Z]);
  980.         tab_indent();
  981.         fprintf(gOutfile, "trans = (%g,%g,%g), index = %g,\n",
  982.             kt * color[X], kt * color[Y], kt * color[Z], i_of_r);
  983.         tab_indent();
  984.         fprintf(gOutfile, "dither = 0\n");
  985.  
  986.         tab_dec();
  987.         tab_indent();
  988.         fprintf(gOutfile, ")\n");
  989.         fprintf(gOutfile, "\n");
  990.         break;
  991.  
  992.     case OUTPUT_RAYSHADE:
  993.         txname = create_surface_name(name, gTexture_count);
  994.         tab_indent();
  995.         fprintf(gOutfile, "surface %s\n", txname);
  996.         tab_inc();
  997.  
  998.         tab_indent();
  999.         fprintf(gOutfile, "ambient %g %g %g\n",
  1000.            ka * color[X], ka * color[Y], ka * color[Z]);
  1001.         tab_indent();
  1002.         fprintf(gOutfile, "diffuse %g %g %g\n",
  1003.            kd * color[X], kd * color[Y], kd * color[Z]);
  1004.  
  1005.         if (shine != 0) {
  1006.         tab_indent();
  1007.         fprintf(gOutfile, "specular %g %g %g\n", shine, shine, shine);
  1008.         tab_indent();
  1009.         fprintf(gOutfile, "specpow %g\n", phong_pow);
  1010.         }
  1011.  
  1012.         if (ks != 0) {
  1013.         if (shine == 0.0) {
  1014.             /* If there is no Phong highlighting, but there is
  1015.                reflectivity, then we need to define the color of
  1016.                specular reflections */
  1017.             tab_indent();
  1018.             fprintf(gOutfile, "specular 1.0 1.0 1.0\n");
  1019.             tab_indent();
  1020.             fprintf(gOutfile, "specpow 0.0\n");
  1021.         }
  1022.         tab_indent();
  1023.         fprintf(gOutfile, "reflect %g\n", ks);
  1024.         }
  1025.  
  1026.         if (kt != 0) {
  1027.         tab_indent();
  1028.         fprintf(gOutfile, "transp %g index %g\n", kt, i_of_r);
  1029.         }
  1030.  
  1031.         tab_dec();
  1032.         tab_indent();
  1033.         break;
  1034.  
  1035.     case OUTPUT_RTRACE:
  1036.         if (shine > 0 && ks == 0.0) ks = shine;
  1037.         fprintf(gOutfile, "1 %g %g %g %g %g %g %g %g %g %g 0 %g %g %g\n",
  1038.             color[X], color[Y], color[Z],
  1039.             kd, kd, kd,
  1040.             ks, ks, ks,
  1041.             (phong_pow > 100.0 ? 100.0 : phong_pow),
  1042.             kt, kt, kt);
  1043.         break;
  1044.  
  1045.     case OUTPUT_OBJ:
  1046.         txname = create_surface_name(name, gTexture_count);
  1047.         fprintf(gOutfile, "usemtl %s\n", txname);
  1048.         break;
  1049.  
  1050.     case OUTPUT_RAWTRI:
  1051.         txname = create_surface_name(name, gTexture_count);
  1052.         break;
  1053.  
  1054.     case OUTPUT_ART:
  1055.         tab_indent();
  1056.         fprintf(gOutfile, "colour %g, %g, %g\n",
  1057.             color[X], color[Y], color[Z]);
  1058.         tab_indent();
  1059.         fprintf(gOutfile, "ambient %g, %g, %g\n",
  1060.             color[X] * 0.05, color[Y] * 0.05, color[Z] * 0.05);
  1061.  
  1062.         if (ks != 0.0) {
  1063.         tab_indent();
  1064.         fprintf(gOutfile, "material %g, %g, %g, %g\n",
  1065.                 i_of_r, kd, ks, phong_pow);
  1066.         } else {
  1067.         tab_indent();
  1068.         fprintf(gOutfile, "material %g, %g, 0.0, 0.0\n",
  1069.                 i_of_r, kd);
  1070.         }
  1071.  
  1072.         tab_indent();
  1073.         fprintf(gOutfile, "reflectance %g\n", ks);
  1074.         tab_indent();
  1075.         fprintf(gOutfile, "transparency %g\n", kt);
  1076.         fprintf(gOutfile, "\n");
  1077.         break;
  1078.       case OUTPUT_RIB:
  1079.         fprintf(gOutfile, "\n");
  1080.         if (name != NULL)
  1081.           fprintf(gOutfile, "Attribute \"identifier\" \"name\" \"%s\"\n",
  1082.               name);
  1083.         fprintf(gOutfile, "Color [ %#g %#g %#g ]\n",
  1084.             color[X], color[Y], color[Z]);
  1085.         fprintf(gOutfile, "Surface \"plastic\" \"Ka\" %#g \"Kd\" %#g"
  1086.             " \"Ks\" %#g \"roughness\" %#g \n",
  1087.             ka, kd, shine, 1.0/phong_pow);
  1088.         break;
  1089.       case OUTPUT_DXF:
  1090.         break;
  1091.       }
  1092.  
  1093.     /* Stash away the current texture name */
  1094.     gTexture_name = txname;
  1095.  
  1096.     return txname;
  1097. }
  1098.